home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 1998 September / Macworld (1998-09).dmg / Shareware World / Info / For Developers / MacZoop 1.8.3 / Required Classes / Z Sources / ZObjectArray.cpp < prev    next >
Text File  |  1998-07-10  |  9KB  |  331 lines

  1. /*************************************************************************************************
  2. *
  3. *
  4. *            MacZoop - "the framework for the rest of us"         
  5. *
  6. *
  7. *
  8. *            ZObjectArray.cpp    -- a container for objects (template class)
  9. *
  10. *
  11. *
  12. *
  13. *
  14. *            © 1996, Graham Cox
  15. *
  16. *
  17. *
  18. *
  19. *************************************************************************************************/
  20.  
  21.  
  22. #include    "ZObjectArray.h"
  23. #include    "ZErrors.h"
  24. #include    "ZDefines.h"
  25. #include    "ZStream.h"
  26.  
  27. /*---------------------------------***  CONSTRUCTOR  ***---------------------------------*/
  28.  
  29. template <class T> ZObjectArray<T>::ZObjectArray()
  30.     : ZArray( sizeof(T*) )
  31. {
  32.     classID = CLASS_ZObjectArray;
  33.     
  34.     // we manipulate our handle via <o> rather than <a> so we can take advantage
  35.     // of direct register copies, etc for maximum performance, which is what this
  36.     // class is all about (it avoids BlockMove).
  37.     
  38.     o = (T***) a;
  39. }
  40.  
  41. /*----------------------------------***  GETOBJECT  ***----------------------------------*/
  42. /*    
  43. return the object at <index>
  44. -----------------------------------------------------------------------------------------*/
  45.  
  46. template <class T> T*    ZObjectArray<T>::GetObject( const long index )
  47. {
  48.     // gets the item at position <index> in the array. Index is one-based.
  49.     
  50.     if ((index < 1) || (index > numElements))
  51.         FailOSErr( kIndexOutOfRangeErr );
  52.         
  53.     return ((*o)[index - 1]);
  54. }
  55.  
  56.  
  57. /*--------------------------------***  DELETEOBJECT  ***---------------------------------*/
  58. /*    
  59. delete the object at <index> from the array. Does not dispose of the object itself
  60. -----------------------------------------------------------------------------------------*/
  61.  
  62. template <class T> void    ZObjectArray<T>::DeleteObject(T* item)
  63. {
  64.     long    index;
  65.     
  66.     index = FindIndex( item );
  67.     
  68.     if (index > 0)
  69.         DeleteItem ( index );
  70. }
  71.  
  72.  
  73. /*---------------------------------***  DISPOSEALL  ***----------------------------------*/
  74. /*    
  75. disposes of all of the objects in the array
  76. -----------------------------------------------------------------------------------------*/
  77.  
  78. template <class T> void    ZObjectArray<T>::DisposeAll()
  79. {
  80.     // calls ForgetObject for every object in the array, then forces the array empty. Since
  81.     // it is possible for ForgetObject to modify this array, we iterate in reverse order.
  82.     
  83.     long    i = numElements;
  84.     T*        p;
  85.     
  86.     while(i--)
  87.     {
  88.         p = (*o)[i];
  89.         
  90.         if (p)
  91.             ForgetObject(p);
  92.     }
  93.  
  94.     SetHandleSize( a, 0 );
  95.     numElements = 0;
  96. }
  97.  
  98.  
  99. /*----------------------------------***  DOFOREACH  ***----------------------------------*/
  100. /*    
  101. calls the grovelling function for every object in the array
  102. -----------------------------------------------------------------------------------------*/
  103.  
  104. template <class T> void    ZObjectArray<T>::DoForEach( IteratorProcPtr aProc, const long ref )
  105. {
  106.     // calls the grovelling function for every object in the array.
  107.     
  108.     if (aProc && (numElements > 0))
  109.     {
  110.         long    i = numElements;
  111.         
  112.         while(i)
  113.             (*aProc)((*o)[--i] , ref);
  114.     }
  115. }
  116.  
  117.  
  118. /*-----------------------------------***  CONTAINS  ***----------------------------------*/
  119. /*    
  120. returns TRUE if the object can be found in the array
  121. -----------------------------------------------------------------------------------------*/
  122.  
  123. template <class T> Boolean    ZObjectArray<T>::Contains(T* item)
  124. {
  125.     return (FindIndex( item ) > 0);
  126. }
  127.  
  128.  
  129. /*--------------------------------***  SETARRAYITEM  ***---------------------------------*/
  130. /*    
  131. overrides the inherited method to store objects in the list avoiding BlockMove().
  132. -----------------------------------------------------------------------------------------*/
  133.  
  134. template <class T> void    ZObjectArray<T>::SetArrayItem( void* item, const long index )
  135. {
  136.     if ((index < 1) || (index > numElements))
  137.         FailOSErr( kIndexOutOfRangeErr );
  138.         
  139.     (*o)[index - 1] = (T*) item;
  140. }
  141.  
  142.  
  143. /*--------------------------------***  GETARRAYITEM  ***---------------------------------*/
  144. /*    
  145. overrides the inherited method to obtain objects in the list avoiding BlockMove().
  146. -----------------------------------------------------------------------------------------*/
  147.  
  148. template <class T> void    ZObjectArray<T>::GetArrayItem( void* item, const long index )
  149. {
  150.     if ((index < 1) || (index > numElements))
  151.         FailOSErr( kIndexOutOfRangeErr );
  152.         
  153.     *(T**)item = ((*o)[index - 1]);
  154. }
  155.  
  156.  
  157. /*-----------------------------***  CONCATENATEARRAY  ***--------------------------------*/
  158. /*    
  159. joins another similar array to the end of this one. The source array must be of the same
  160. type and is uaffected by the copy. Since the arrays contain object refs, note that both
  161. arrays will have the same objects in them after this, so take care.
  162. -----------------------------------------------------------------------------------------*/
  163.  
  164. template <class T> void    ZObjectArray<T>::ConcatenateArray( ZObjectArray<T>* anArray )
  165. {
  166.     ZArray::ConcatenateArray((ZArray*) anArray );
  167. }
  168.  
  169.  
  170.  
  171.  
  172. /*----------------------------------***  FINDINDEX  ***----------------------------------*/
  173. /*    
  174. return the index of the object, or zero if not found.
  175. -----------------------------------------------------------------------------------------*/
  176.  
  177. template <class T> long    ZObjectArray<T>::FindIndex(T* item)
  178. {
  179.     if ( numElements < 1 )
  180.         return 0;
  181.         
  182.     long        i = 0;
  183.     Boolean        found = FALSE;
  184.     
  185.     do
  186.     {
  187.         if ((*o)[i] == item)
  188.         {
  189.             found = TRUE;
  190.             break;
  191.         }    
  192.     }
  193.     while( ++i < numElements );
  194.  
  195.     return ( found? i + 1 : 0 );
  196. }
  197.  
  198.  
  199. /*-------------------------------------***  SWAP  ***------------------------------------*/
  200. /*    
  201. swaps the items at indices a and b- can be used within sorts, etc
  202. -----------------------------------------------------------------------------------------*/
  203.  
  204. template <class T> void    ZObjectArray<T>::Swap( const long itema, const long itemb )
  205. {
  206.     register T* temp;
  207.     
  208.     if ((itema < 1) ||
  209.         (itema > numElements) ||
  210.         (itemb < 1) ||
  211.         (itemb > numElements))
  212.         FailOSErr( kIndexOutOfRangeErr );
  213.         
  214.     temp = GetObject( itema );
  215.     
  216.     (*o)[itema - 1] = (*o)[itemb - 1];
  217.     (*o)[itemb - 1] = temp;
  218. }
  219.  
  220.  
  221. /*-----------------------------------***  MOVEITEM  ***----------------------------------*/
  222. /*    
  223. moves the object at index <curIndex> to the index <newIndex>, displacing other items
  224. as needed. Completely overrides the ZArray method for better efficiency and to eliminate
  225. "pointer to pointer to object" dereferencing difficulties.
  226. -----------------------------------------------------------------------------------------*/
  227.  
  228. template <class T> void    ZObjectArray<T>::MoveItem( const long curIndex, const long newIndex )
  229. {
  230.     register T*    temp;
  231.     
  232.     if ((curIndex < 1)                 ||
  233.         (curIndex > numElements)     ||
  234.         (newIndex < 1)                 ||
  235.         (newIndex > numElements))
  236.         FailOSErr( kIndexOutOfRangeErr );
  237.     
  238.     // don't do anything if indices the same (not an error)
  239.     
  240.     if ( curIndex != newIndex )
  241.     {    
  242.         temp = GetObject( curIndex );
  243.         
  244.         DeleteItem( curIndex );
  245.         InsertItem( temp, newIndex );
  246.         
  247.         SendMessage( msgArrayItemMoved, (void*) newIndex );
  248.     }
  249. }
  250.  
  251. /*---------------------------------***  MOVETOFRONT  ***---------------------------------*/
  252. /*    
  253. moves the object at index <curIndex> to the front of the list (1)
  254. -----------------------------------------------------------------------------------------*/
  255.  
  256. template <class T> void    ZObjectArray<T>::MoveToFront( const long index )
  257. {
  258.     MoveItem( index, 1 );
  259. }
  260.  
  261. /*----------------------------------***  MOVETOBACK  ***---------------------------------*/
  262. /*    
  263. moves the object at index <curIndex> to the back of the list (n)
  264. -----------------------------------------------------------------------------------------*/
  265.  
  266. template <class T> void    ZObjectArray<T>::MoveToBack( const long index )
  267. {
  268.     MoveItem( index, CountItems());
  269. }
  270.  
  271.  
  272. /*-------------------------------***  WRITETOSTREAM  ***--------------------------------*/
  273. /*    
  274. write entire array object to stream. Since this array holds objects, we save each one
  275. as an object reference, not the same way that ZArray works. Note that <T> must be derived
  276. from ZObject and registered with <gClasses> for this to work, but when it does work the
  277. power this unleashes is astonishing! 
  278. ----------------------------------------------------------------------------------------*/
  279.  
  280. template <class T> void    ZObjectArray<T>::WriteToStream( ZStream* aStream )
  281. {
  282.     ZComrade::WriteToStream( aStream );
  283.     
  284.     register long    i;
  285.     
  286.     // count of objects to follow:
  287.     
  288.     aStream->WriteLong( numElements );
  289.     
  290.     // write the object references as needed:
  291.     
  292.     for ( i = 1; i <= numElements; i++ )
  293.         aStream->WriteObject( GetObject( i ));
  294. }
  295.  
  296. /*------------------------------***  READFROMSTREAM  ***--------------------------------*/
  297. /*    
  298. read entire array back from stream. This refills the array with objects built from the
  299. stream. These objects are equivalent to the ones saved in the stream originally, and
  300. have the same type and function.
  301. ----------------------------------------------------------------------------------------*/
  302.  
  303.  
  304. template <class T> void    ZObjectArray<T>::ReadFromStream( ZStream* aStream )
  305. {
  306.     ZComrade::ReadFromStream( aStream );
  307.     
  308.     register T*        temp;
  309.     register long    i, numObjects;
  310.     
  311.     aStream->ReadLong( &numObjects );
  312.     
  313.     // size the storage handle as needed to hold this many objects:
  314.     
  315.     if ( numElements != numObjects )
  316.     {
  317.         SetHandleSize( a, numObjects * blkSize );
  318.         FailMemError();
  319.         
  320.         numElements = numObjects;
  321.     }
  322.     
  323.     for ( i = 1; i <= numObjects; i++ )
  324.     {
  325.         temp = (T*) aStream->ReadObject();
  326.         SetArrayItem( temp, i );
  327.     }
  328. }
  329.  
  330.  
  331.